package cn.wolfcode.shop.cloud.service.impl;

import cn.wolfcode.shop.cloud.common.BusinessException;
import cn.wolfcode.shop.cloud.common.Result;
import cn.wolfcode.shop.cloud.domain.Good;
import cn.wolfcode.shop.cloud.feign.GoodFeignApi;
import cn.wolfcode.shop.cloud.mapper.SeckillGoodMapper;
import cn.wolfcode.shop.cloud.msg.SeckillCodeMsg;
import cn.wolfcode.shop.cloud.service.ISeckillGoodService;
import cn.wolfcode.shop.cloud.service.RedisService;
import cn.wolfcode.shop.cloud.util.SeckillKeyPrefix;
import cn.wolfcode.shop.cloud.vo.SeckillGoodVo;
import domain.SeckillGood;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class SeckillGoodServiceImpl implements ISeckillGoodService {
    @Autowired
    private SeckillGoodMapper seckillGoodMapper;
    @Autowired
    private GoodFeignApi goodFeignApi;
    @Autowired
    private RedisService redisService;


    @Override
    public List<SeckillGoodVo> query() {
        //1.查询出来秒杀商品数据List<SeckillGood> list
        List<SeckillGood> seckillGoods = seckillGoodMapper.querySeckillGoods();

        return common(seckillGoods);
    }

    //将获取商品信息和秒杀商品信息的拼接Vo对象的方法抽取出来
    public List<SeckillGoodVo> common(List<SeckillGood> seckillGoods) {
        //2.把商品的id放在一个set集合中
        Set<Long> goodIds = new HashSet<>();
        for (SeckillGood seckillGood : seckillGoods) {
            goodIds.add(seckillGood.getGoodId());
        }
        //把set集合转换成list集合

        //3.根据id集合远程调用商品服务区查询数据
        Result<List<Good>> result = goodFeignApi.queryGoods(goodIds);
        if (result == null || result.getCode() != 200) {
            throw new BusinessException(SeckillCodeMsg.REMOTE_GOODS_EEEOR);
        }

        //4.在内存中进行聚合操作
        Map<Long, Good> data = new HashMap<>();
        for (Good good : result.getData()) {
            data.put(good.getId(), good);
        }
        //5.返回list<Vo>
        List<SeckillGoodVo> vos = new ArrayList<>();
        for (SeckillGood seckillGood : seckillGoods) {
            SeckillGoodVo vo = new SeckillGoodVo();
            Good good = data.get(seckillGood.getGoodId());//获取商品对象
            BeanUtils.copyProperties(good, vo);
            //此处可能出现属性的覆盖，导致goodId被覆盖
            BeanUtils.copyProperties(seckillGood, vo);
            //把vo分装到List<SeckillGoodVo>集合中
            vos.add(vo);
        }
        return vos;
    }


    @Override
    public SeckillGoodVo queryById(Long seckillId) {
        SeckillGood seckillGood = seckillGoodMapper.queryById(seckillId);
        ArrayList arrayList = new ArrayList();
        arrayList.add(seckillGood);
        List<SeckillGoodVo> vos = common(arrayList);
        return vos.get(0);
    }

    @Override
    public int decr(Long seckillId) {
        return seckillGoodMapper.decr(seckillId);
    }

    @Override
    public SeckillGoodVo queryByIdCache(Long seckillId) {

        SeckillGoodVo vo = redisService.hget(SeckillKeyPrefix.SECKILL_HASH, "",
                seckillId + "", SeckillGoodVo.class);
        //从redis中把库存取出来
        Integer count = redisService.get(SeckillKeyPrefix.SECKILL_STOCK_COUNT, seckillId+"", Integer.class);
        if (count <= 0) {
            count = 0;
        }
        vo.setStockCount(count);
        return vo;

    }

    @Override
    public List<SeckillGoodVo> queryCache() {
        Map<String, SeckillGoodVo> map = redisService.hgetAll(SeckillKeyPrefix.SECKILL_HASH, "", SeckillGoodVo.class);
        Collection<SeckillGoodVo> values = map.values();
        ArrayList<SeckillGoodVo> seckillGoodVos = new ArrayList<>(values);
        for (SeckillGoodVo seckillGoodVo : seckillGoodVos) {
            Integer count = redisService.get(SeckillKeyPrefix.SECKILL_STOCK_COUNT, "" + seckillGoodVo.getId(), Integer.class);
            if (count <= 0) {
                count = 0;
            }
            seckillGoodVo.setStockCount(count);
        }
        return seckillGoodVos;
    }

    @Override
    //回补真实库存
    public void incrCount(Long seckillId) {
        seckillGoodMapper.incrCount(seckillId);
    }

    @Override
    //回补预库存
    public void syncPreCount(Long goodId) {
        SeckillGoodVo vo = queryById(goodId);
        //直接覆盖秒杀库存
        redisService.set(SeckillKeyPrefix.SECKILL_STOCK_COUNT,""+goodId,vo.getStockCount());
    }
}
